﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace RLE_Encoder
{
    public partial class RLECompressorForm : Form
    {
        List<RLEPacket> Packets = new List<RLEPacket>();
        int bitmapWidth = 0;
        int bitmapHeight = 0;

        public RLECompressorForm()
        {
            InitializeComponent();
        }

        private void loadButton_Click(object sender, EventArgs e)
        {

            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "Select a file";
            ofd.Filter = "Bitmap|*.bmp";

            if (ofd.ShowDialog() == DialogResult.OK)
            {

                filenameBox.Text = ofd.FileName;

                Packets.Clear();
                listBox1.Items.Clear();

                Bitmap bitmap = (Bitmap)Bitmap.FromFile(ofd.FileName);
                bitmapWidth = bitmap.Width;
                bitmapHeight = bitmap.Height;
                //if (bitmap.Width != 128 || bitmap.Height != 64)
                //{
                //    MessageBox.Show("Bitmap is not correct size!");
                //    return;
                //}
                int x=0, y = 0, page = 0;

                byte pattern = 0;
                byte count = 0;

                while (page < bitmapHeight/8)
                {
                    x = 0;
                    while (x < bitmap.Width)
                    {
                        y = 8 * page;

                        byte currPattern = 0;
                        byte mask = 1;
                        for (int offset = 0; offset < 8; offset++)
                        {
                            Color currCol = bitmap.GetPixel(x, y+offset);
                            if (currCol.R == 255)
                            {
                                currPattern |= mask;
                            }
                            mask *= 2;
                        }
                        

                        if (pattern != currPattern)
                        {
                            pattern ^= 0xFF; //invert the mask (255 = white -> 0 = white)
                            if(count > 0)Packets.Add(new RLEPacket() { Count = count, Pattern = pattern });
                            pattern = currPattern;
                            count = 1;
                        }
                        else count++;

                        x++;
                    }

                    //do not allow pages to overflow
                    pattern ^= 0xFF; //invert the mask (255 = white -> 0 = white)
                    if (count > 0) Packets.Add(new RLEPacket() { Count = count, Pattern = pattern });
                    pattern = 0;
                    count = 0;

                    page++;
                }

                foreach (RLEPacket packet in Packets)
                {
                    listBox1.Items.Add(packet.Count + ":" + packet.Pattern);
                }
                
                statusLabel.Text = "Original bitmap size: " + (bitmap.Width * bitmap.Height / 8) + ", RLE size: " + (1 + 2 * Packets.Count);
                bitmap.Dispose();

            }

        }

        private void writeButton_Click(object sender, EventArgs e)
        {
            StringBuilder outputString = new StringBuilder("const unsigned char RLEImage [] = {"+bitmapWidth+","+bitmapHeight);
            
            foreach (RLEPacket packet in Packets)
            {
                outputString.Append(",");
                outputString.Append(packet.Count);
                outputString.Append(",");
                outputString.Append(packet.Pattern);
            }
            outputString.Append(",0};");

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "Header File|*.h|C Source File|*.c";
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                StreamWriter sw = new StreamWriter(File.Open(sfd.FileName, FileMode.Create));
                sw.Write(outputString.ToString());
                sw.Close();
            }
        }
    }

    public struct RLEPacket
    {
        public byte Count;
        public byte Pattern;
    }
}
